#include "vl_timer.h"

#include <unistd.h>

using namespace VL;

/**
 * @Author: CimZzz
 * @Date: 2022-09-05 11:09:44
 * 
 * 构造函数
 * 
 * 
 * @param callback 定时器回调
 * @param begin 是否立刻开始定时器
 * @param period 定时间触发间隔时间, 单位毫秒
 */
VLTimer::VLTimer(TimerCallback callback, bool begin, time_t period): callback(callback),
	period(period), isBegin(false), manualScheduleCount(0) {
	if(begin) {
		this->beginSchedule();
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-09-05 11:13:48
 * 
 * 析构函数
 */
VLTimer::~VLTimer() {
	this->stopSchedule();
}

/**
 * @Author: CimZzz
 * @Date: 2022-09-05 11:11:34
 * 
 * 开始调度
 */
void VLTimer::beginSchedule() {
	this->mutex.lock();
	if(this->isBegin) {
		this->mutex.unlock();
		return;
	}
	this->isBegin = true;
	this->threadPtr.reset(new std::thread([&]{
		auto lastTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
		time_t calcTime = 0;
		while(this->isBegin) {
			// 判断是否为手动调度
			bool isManual = false;
			this->mutex.lock();
			if(this->manualScheduleCount > 0) {
				isManual = true;
				this->manualScheduleCount --;
			}
			this->mutex.unlock();
			if(isManual) {
				// 手动调度直接执行
				this->callback();
				continue;
			}
			auto currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
			auto currentTimeDiff = (currentTime - lastTime).count();
			if(currentTimeDiff <= 100) {
				currentTimeDiff = 100;
			}
			calcTime += currentTimeDiff;
			if(calcTime >= this->period) {
				calcTime = 0;
				this->callback();
			}
			lastTime = currentTime;
			// 等待 100 毫秒
			usleep(100000);
		}
	}));
	this->mutex.unlock();
}

/**
 * @Author: CimZzz
 * @Date: 2022-09-05 11:11:50
 * 
 * 停止调度
 */
void VLTimer::stopSchedule() {
	this->mutex.lock();
	if(!this->isBegin) {
		this->mutex.unlock();
		return;
	}
	auto tmpThreadPtr = std::move(this->threadPtr);
	this->isBegin = false;
	this->manualScheduleCount = 0;
	this->mutex.unlock();
	if(tmpThreadPtr.get() != nullptr) {
		if(tmpThreadPtr->joinable()) {
			tmpThreadPtr->join();
		}
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-09-07 16:35:14
 * 
 * 立即调度一次
 */
void VLTimer::scheduleOnce() {
	this->mutex.lock();
	if(!this->isBegin) {
		this->mutex.unlock();
		return;
	}
	this->manualScheduleCount ++;
	this->mutex.unlock();
}


/**
 * @Author: CimZzz
 * @Date: 2023-02-28 15:13:53
 * 
 * 等待计时器停止
 */
void VLTimer::waitTimerStop() {
	this->mutex.lock();
	if(!this->isBegin) {
		this->mutex.unlock();
		return;
	}
	auto tmpThreadPtr = this->threadPtr;
	this->mutex.unlock();

	if(tmpThreadPtr.get() != nullptr) {
		if(tmpThreadPtr->joinable()) {
			tmpThreadPtr->join();
		}
	}
}